home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Text⁄Files / text to macwrite ƒ / txtomw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-09  |  11.2 KB  |  451 lines  |  [TEXT/MPS ]

  1. /*
  2.     txtomw.c
  3.  
  4.     This is a skeleton program for converting text files into MacWrite documents.
  5.     It is written in MPW C 2.0.2 but it should be easy to modify it so it compiles
  6.     under other C compilers (e.g. under UNIX as someone wanted to do) if you have
  7.     the necessary Macintosh header files.
  8.  
  9.     Format changes can be added to the text according to some rules. As it is, only
  10.     one formatting code is recognized and that is a '>' to signify the beginning of
  11.     italic text and '<' to signify the end. As I used it originally there were far
  12.     more complex formatting codes and it should be fairly easy to add them in.
  13.  
  14.     Macintosh Tech Note #12 should be helpful in understanding the workings of
  15.     the program. When needed I peeked into genuin MacWrite files and saw what
  16.     was done. I followed very closely what MacWrite does but something of what
  17.     my program does may be unnecessary.
  18.  
  19.     The code is not to heavily commented, but should (hopefully) be reasonably
  20.     clear.
  21.  
  22.     If you are using MPW C 2.0.2 you can compile the file without modifications
  23.     using these commands:
  24.         C txtomw.c
  25.         Link txtomw.c.o ∂
  26.             "{CLibraries}"CRuntime.o ∂
  27.             "{CLibraries}"StdCLib.o ∂
  28.             "{CLibraries}"CInterface.o ∂
  29.             -o txtomw
  30.  
  31.  
  32.     I would be happy to hear from you if this is to any use to you and even
  33.     happier if you send me the nifty improvements you make to it.
  34.     Please feel free to pass this on to others, preferably with my name included.
  35.  
  36.     Gisli Runar Hjaltason
  37.     University of Iceland
  38.         (undergrad til ~1990)
  39.     UUCP:
  40.         grh@rhi.hi.is
  41.         grh@krafla.UUCP
  42.     BIX:
  43.         gisli
  44.     DELPHI:
  45.         GISLI
  46.     Snail mail:
  47.         Njalsgata 12
  48.         IS-101 Reykjavik
  49.         ICELAND
  50. */
  51.  
  52. /* Standard C headers */
  53. #include    <stdio.h>
  54. #include    <ioctl.h>
  55. #include    <string.h>
  56.  
  57. /* Macintosh headers (directly used functions and types in comments) */
  58. #include    <types.h>
  59.     /* Handle */
  60. #include    <quickdraw.h>
  61.     /* InitGraf */
  62. #include    <fonts.h>
  63.     /* InitFonts */
  64. #include    <windows.h>
  65.     /* InitWindows */
  66. #include    <dialogs.h>
  67.     /* InitDialogs */
  68. #include    <resources.h>
  69.     /* CreateResFile, OpenResFile, RmveResource, GetResource,
  70.             AddResource, CloseResFile */
  71. #include    <packages.h>
  72.     /* NumToString, SFGetFile, SFReply */
  73. #include    <memory.h>
  74.     /* MaxApplZone */
  75. #include    <files.h>
  76.     /* GetFInfo, SetFInfo, Allocate, SetVol, FInfo */
  77. #include    <osutils.h>
  78.     /* PtrToHand */
  79. #include    <strings.h>
  80.     /* p2cstr */
  81.  
  82. /* Note: some of these are unnecessary in MPW C because the functions used
  83.         are not declared in the corresponding header file */
  84.  
  85. /* MacWrite header */
  86. #include    "txtomw.h"
  87.  
  88. #define NEWLINE    0x0D
  89.  
  90. #define BUFSIZ    4096
  91. #define MAXPARS    1000
  92.  /* Maximum number of paragraphs that are to be in a single output file.
  93.         This can be as high as 32000 but then the "pars" array takes about 512K.
  94.         Of course I could have resized it dynamically, but I didn't... */
  95.  
  96. char        *getdoc();
  97.  
  98.     struct doc_header    dhead;
  99.     FILE            *infile, *outfile;
  100.     short            outcount;
  101.     par_info    *pars;
  102.     par_info    headpars[2];
  103.     par_info    footpars[2];
  104.     short            parcount;
  105.     format        fontch[200];
  106.     long            formatcount;
  107.     par_data    *cur_par;
  108.     ruler            rul;
  109.     long            curpos, prevpos;
  110.     long            previnpos;
  111.     char            filename[64], outfilename[64];
  112.     unsigned char    *buffer;
  113.  
  114. main()
  115. {
  116.     register int    i, j;
  117.     short    length, linelength, cursize, curstyle, curfont, staerd;
  118.  
  119.     InitGraf(&qd.thePort);
  120.     InitFonts();
  121.     InitWindows();
  122.     InitDialogs(0);
  123.     MaxApplZone();
  124.  
  125.     memset(&dhead, 0, sizeof(dhead));
  126.     dhead.version = 6;
  127.     dhead.ruler_display = -1;
  128.     dhead.active_doc = -1;    /* makes MacWrite recalculate line heights
  129.                                                             and paragraph positions */
  130.     dhead.start_page = 1;
  131.  
  132.     dhead.header_paragraphs = 2;
  133.     dhead.footer_paragraphs = 2;
  134.     dhead.start_page = 1;
  135.     dhead.main.start_sel = dhead.main.end_sel = 0x10000;
  136.     dhead.main.page_number_pos = 0xFFF2001E;
  137.     dhead.main.date_pos = 0xFFF200A6;
  138.     dhead.main.time_pos = 0xFFF20174;
  139.     dhead.main.unused = -1;
  140.     dhead.main.oval_redraw = -1;
  141.     dhead.main.active_style = -1;
  142.     dhead.main.active_font = -1;
  143.  
  144.     memcpy(&dhead.header, &dhead.main, sizeof(wind_var));
  145.     memcpy(&dhead.footer, &dhead.main, sizeof(wind_var));
  146.  
  147.     buffer = (unsigned char    *)malloc(BUFSIZ);
  148.     if (!buffer)
  149.         exit();
  150.     cur_par = (par_data *)malloc(BUFSIZ+sizeof(par_data));
  151.     if (!cur_par)
  152.         exit();
  153.     pars = (par_info *)malloc(MAXPARS*sizeof(par_info));
  154.     if (!pars)
  155.         exit();
  156.     memset(pars, 0, MAXPARS*sizeof(par_info));
  157.  
  158. /* I assume that only one kind of ruler is needed. You should be able to
  159.         add some more easily. */
  160.     rul.left_margin = 4;
  161.     rul.right_margin = 480;
  162.     rul.just = 3;
  163.     rul.tab_numb = 1;
  164.     rul.spacing = 0;
  165.     rul.indent = 4;
  166.     rul.tab_array[0] = -460;
  167.  
  168.     while (1) {
  169.         infile = fopen(getdoc(filename), "r");
  170.  
  171.         previnpos = 0;
  172.         outcount = parcount = curpos = 0;
  173.  
  174.         curfont = times;
  175.         cursize = 12;
  176.         curstyle = normal;
  177.  
  178.         open_outfile();
  179.  
  180.         while (!(feof(infile))) {
  181.             if (ftell(infile) - previnpos > 50000 || parcount >= MAXPARS) {
  182.                 /* Make a new output file if the current output file
  183.                         exceeds 50000 characters or MAXPARS paragraphs.
  184.                         The limitation of the number of characters is simply
  185.                         practical; MacWrite is slow with large files. */
  186.  
  187.                 previnpos = ftell(infile);
  188.  
  189.                 close_outfile();
  190.  
  191.                 open_outfile();
  192.             }
  193.  
  194.             fgets(buffer, BUFSIZ, infile);
  195.  
  196.             linelength = strlen(buffer);
  197.  
  198.             i = 0;
  199.             while (i < linelength) {
  200.                 formatcount = 1;
  201.                 fc(fontch, 0, cursize, curstyle, curfont);
  202.  
  203.                 for (j = 0; i < linelength; ++i) {
  204.                     switch (buffer[i]) {
  205.  
  206.                         case '>':
  207.                             curstyle = italic;
  208.                             fc(fontch + formatcount++, j, cursize, curstyle, curfont);
  209.                             break;
  210.  
  211.                         case '<':
  212.                             curstyle = normal;
  213.                             fc(fontch + formatcount++, j, cursize, curstyle, curfont);
  214.                             break;
  215.  
  216.                         /* add more as needed */
  217.  
  218.                         default:
  219.                             cur_par->text[j++] = buffer[i];
  220.                             break;
  221.                     }
  222.                 }
  223.  
  224.     write_par:    /* jump to this label if you want to make a new paragraph in the
  225.                                     middle of an input line (it's seems to me to be the cleanest
  226.                                     way to break out of the 'switch' statement and the 'for' loop
  227.                                     at once) */
  228.                 if (cur_par->text[j-1] != NEWLINE)
  229.                     cur_par->text[j++] = NEWLINE;
  230.                 cur_par->length = j;
  231.                 prevpos = curpos;
  232.                 length = (j + 3) & -2;
  233.                 fwrite(cur_par, length, 1, outfile);
  234.                 putw((formatcount * sizeof(format))<<16, outfile);
  235.                 fseek(outfile, -2, 1);
  236.                 /* backup 2 bytes because 'putw' puts 4 bytes
  237.                         (why isn't there a 2 byte 'put') */
  238.                 fwrite(fontch, sizeof(format), formatcount, outfile);
  239.                 curpos = prevpos + length + 2 + formatcount * sizeof(format);
  240.  
  241.                 pars[parcount].height = 1;    /* text paragraph (MacWrite will calculate
  242.                                                                                 the correct height) */
  243.                 pars[parcount].par_data = (char *)prevpos;
  244.                 pars[parcount].par_len = curpos - prevpos;
  245.                 parcount++;
  246.             }
  247.         }
  248.  
  249.         close_outfile();
  250.         fclose(infile);
  251.     }
  252. }
  253.  
  254. open_outfile()
  255. {
  256.     FInfo        fuppl;
  257.     short        skrarnr;
  258.     long        length;
  259.     char        num[5];
  260.     Handle    sh;
  261.  
  262.     NumToString(++outcount, num);
  263.     strcpy(outfilename, filename);
  264.     strcat(strcat(outfilename, num), ".mw");
  265.     /* name the output file with  the input filename
  266.             with a following number and suffix .mw */
  267.     outfile = fopen(outfilename, "w");
  268.  
  269.     GetFInfo(outfilename, 0, &fuppl);
  270.     fuppl.fdType = 'WORD';
  271.     fuppl.fdCreator = 'MACA';
  272.     SetFInfo(outfilename, 0, &fuppl);
  273.  
  274.     /* the following 6 statements are really unnecessary unless you have to
  275.             open the files with Microsoft Word, even then the first statement
  276.             should suffice (i.e. make an empty resource fork) */
  277.     CreateResFile(outfilename);
  278.     skrarnr = OpenResFile(outfilename);
  279.     RmveResource(GetResource('STR ', 700));
  280.     PtrToHand("\p etnroaisdlhcfp", &sh, 16);
  281.     AddResource(sh, 'STR ', 700, "");
  282.     CloseResFile(skrarnr);
  283.  
  284.     parcount = 1;
  285.  
  286.     ioctl(fileno(outfile), FIOREFNUM, &skrarnr);
  287.     length = sizeof(dhead);
  288.     Allocate(skrarnr, &length);
  289.     ioctl(fileno(outfile), FIOSETEOF, length);
  290.     fseek(outfile, sizeof(dhead), 0);
  291.  
  292.     /* make a ruler and an empty line for the footer and header */
  293.  
  294.     prevpos = ftell(outfile);
  295.     fwrite(&rul, sizeof(rul), 1, outfile);
  296.     curpos = prevpos + sizeof(rul);
  297.  
  298.     fc(fontch, 0, 12, normal, times);
  299.  
  300.     footpars[0].height = 0;
  301.     footpars[0].par_data = (char *)prevpos;
  302.     footpars[0].par_len = curpos - prevpos;
  303.  
  304.     prevpos = curpos;
  305.     putw(sizeof(format), outfile);
  306.     fwrite(fontch, sizeof(format), 1, outfile);
  307.     curpos = prevpos + 4 + sizeof(format);
  308.  
  309.     footpars[1].height = 1;
  310.     footpars[1].par_data = (char *)prevpos;
  311.     footpars[1].par_len = curpos - prevpos;
  312.  
  313.     dhead.footer.info_array = (char *)prevpos;
  314.     dhead.footer.info_length = 2 * sizeof(par_info);
  315.  
  316.     prevpos = curpos;
  317.     fwrite(&rul, sizeof(rul), 1, outfile);
  318.     curpos = prevpos + sizeof(rul);
  319.  
  320.     headpars[0].height = 0;
  321.     headpars[0].par_data = (char *)prevpos;
  322.     headpars[0].par_len = sizeof(rul);
  323.  
  324.     prevpos = curpos;
  325.     putw(sizeof(format), outfile);
  326.     fwrite(fontch, sizeof(format), 1, outfile);
  327.     curpos = prevpos + 4 + sizeof(format);
  328.  
  329.     headpars[1].height = 1;
  330.     headpars[1].par_data = (char *)prevpos;
  331.     headpars[1].par_len = curpos - prevpos;
  332.  
  333.     /* and a ruler for the main part */
  334.  
  335.     prevpos = curpos;
  336.     fwrite(&rul, sizeof(rul), 1, outfile);
  337.     curpos = prevpos + sizeof(rul);
  338.  
  339.     pars[0].height = 0;
  340.     pars[0].par_data = (char *)prevpos;
  341.     pars[0].par_len = sizeof(rul);
  342. }
  343.  
  344.  
  345. close_outfile()
  346. {
  347.     memset(buffer, 0, parcount > 2 ? parcount * 2 : 4);
  348.     /* buffer is used for the lineheight arrays, the linheight is set
  349.             to 0 (zero) for all paragraphs */
  350.  
  351.     /* now I make the paragraph info for the header and footer */
  352.  
  353.     prevpos = curpos;
  354.     fwrite(buffer, 4, 1, outfile);
  355.     curpos = prevpos + 4;
  356.  
  357.     dhead.footer.linheight_array = (char *)prevpos;
  358.     dhead.footer.linheight_len = 4;
  359.  
  360.     prevpos = curpos;
  361.     fwrite(footpars, sizeof(par_info), 2, outfile);
  362.     curpos = prevpos + 2 * sizeof(par_info);
  363.  
  364.     dhead.footer.info_array = (char *)prevpos;
  365.     dhead.footer.info_length = 2 * sizeof(par_info);
  366.  
  367.     prevpos = curpos;
  368.     fwrite(buffer, 4, 1, outfile);
  369.     curpos = prevpos + 4;
  370.  
  371.     dhead.header.linheight_array = (char *)prevpos;
  372.     dhead.header.linheight_len = 4;
  373.  
  374.     prevpos = curpos;
  375.     fwrite(headpars, sizeof(par_info), 2, outfile);
  376.     curpos = prevpos + 2 * sizeof(par_info);
  377.  
  378.     dhead.header.info_array = (char *)prevpos;
  379.     dhead.header.info_length = 2 * sizeof(par_info);
  380.  
  381.     /* then the paragraph info for the main part */
  382.  
  383.     prevpos = curpos;
  384.     fwrite(buffer, 2, parcount, outfile);
  385.     curpos = prevpos + parcount * 2;
  386.  
  387.     dhead.main.linheight_array = (char *)prevpos;
  388.     dhead.main.linheight_len = parcount * 2;
  389.  
  390.     prevpos = curpos;
  391.     fwrite(pars, sizeof(par_info), parcount, outfile);
  392.     curpos = prevpos + parcount * sizeof(par_info);
  393.  
  394.     dhead.main_paragraphs = parcount;
  395.     dhead.main.info_array = (char *)prevpos;
  396.     dhead.main.info_length = curpos-prevpos;
  397.  
  398.     /* the free list is next */
  399.  
  400.     prevpos = curpos;
  401.     putw(prevpos + 8, outfile);
  402.     putw(0, outfile);
  403.     curpos = prevpos + 8;
  404.  
  405.     dhead.free_list = (char *)prevpos;
  406.     dhead.free_len = dhead.free_alloc = 8;
  407.  
  408.     ioctl(fileno(outfile), FIOSETEOF, ftell(outfile));
  409.  
  410.     /* write out the document header */
  411.  
  412.     rewind(outfile);
  413.     fwrite(&dhead, sizeof(dhead), 1, outfile);
  414.  
  415.     fclose(outfile);
  416. }
  417.  
  418. char *
  419. getdoc(heiti)
  420. char    *heiti;
  421. {
  422.     SFReply            reply;
  423.     Point                pt;
  424.  
  425.     pt.h = pt.v = 82;        /* topleft is in (82,82) */
  426.  
  427.     SFGetFile(&pt, 0, 0, 1, "TEXT", 0, &reply);
  428.     if (!reply.good)
  429.         exit();
  430.  
  431.     SetVol(0, reply.vRefNum);
  432.  
  433.     return(strcpy(heiti, p2cstr(&reply.fName)));
  434. }
  435.  
  436.  
  437. /* This function puts the parameters into a format run. */
  438.  
  439. fc(fp, first_ch, siz, styl, fontnum)
  440. format *fp;
  441. short    first_ch;
  442. char    siz;
  443. char    styl;
  444. short    fontnum;
  445. {
  446.     fp->begin_pos = first_ch;
  447.     fp->size = siz;
  448.     fp->style = styl;
  449.     fp->font_numb = fontnum;
  450. }
  451.